package com.hbzhit.modules.sys.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbzhit.common.exception.RRException;
import com.hbzhit.common.utils.Constant;
import com.hbzhit.common.utils.PageUtils;
import com.hbzhit.common.utils.Query;
import com.hbzhit.common.validator.ValidatorUtils;
import com.hbzhit.common.validator.group.AddGroup;
import com.hbzhit.common.validator.group.UpdateGroup;
import com.hbzhit.config.CacheConfig;
import com.hbzhit.modules.sys.dao.SysOrgDao;
import com.hbzhit.modules.sys.entity.SysOrgEntity;
import com.hbzhit.modules.sys.entity.SysUserEntity;
import com.hbzhit.modules.sys.service.SysOrgService;
import com.hbzhit.modules.sys.service.SysUserService;
import com.hbzhit.modules.sys.vo.SysOrgQueryVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 组织机构
 *
 * @author DING
 **/
@Service("orgService")
@AllArgsConstructor
public class SysOrgServiceImpl extends ServiceImpl<SysOrgDao, SysOrgEntity> implements SysOrgService {
    private final SysUserService sysUserService;

    @Override
    public PageUtils<SysOrgEntity> queryPage(SysOrgQueryVO params) {
        IPage<SysOrgEntity> page = this.page(new Query<SysOrgEntity>().getPage(params), params.queryWrapper());
        return new PageUtils<>(page);
    }

    @Override
    public List<SysOrgEntity> queryList(SysOrgQueryVO params) {
        return this.list(params.queryWrapper());
    }

    @Override
    public List<SysOrgEntity> listAll() {
        return this.list(new LambdaQueryWrapper<SysOrgEntity>()
                .eq(SysOrgEntity::getIsDel, Constant.INT_N)
                .or()
                .eq(SysOrgEntity::getIsDel, Constant.INT_Y)
        );
    }

    @Override
    public boolean save(SysOrgEntity entity) {
        ValidatorUtils.validateEntity(entity, AddGroup.class);
        this.orgSaveValidate(entity);

        boolean ret = super.save(entity);

        //更新缓存
        CacheConfig.orgCache.put(entity.getId(), entity);

        return ret;
    }

    @Override
    public boolean updateById(SysOrgEntity entity) {
        ValidatorUtils.validateEntity(entity, UpdateGroup.class);
        this.orgSaveValidate(entity);

        boolean ret = super.updateById(entity);

        //更新缓存
        CacheConfig.orgCache.put(entity.getId(), entity);

        return ret;
    }

    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        for (Serializable serializable : idList) {
            List<SysOrgEntity> orgs = queryAllChildren((Long) serializable);
            if (CollectionUtil.isNotEmpty(orgs)) {
                throw new RRException("存在下级，不能删除");
            }
            // 判断是否存在关联人员
            int countUser = sysUserService.count(new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getOrgId, serializable));
            if (countUser > 0) {
                throw new RRException("存在关联人员或用户，不能删除");
            }
        }
        boolean ret = super.removeByIds(idList);

        //更新缓存
        idList.forEach(id -> CacheConfig.orgCache.get((Long)id).setIsDel(Constant.INT_Y));

        return ret;
    }

    @Override
    public List<SysOrgEntity> queryAllChildren(Long parentId) {
        List<SysOrgEntity> allList = new ArrayList<>();
        CacheConfig.orgCache.forEach(org -> {
            if (Constant.INT_N == org.getIsDel()) {
                allList.add(org);
            }
        });
        return getAllChildrenList(allList, parentId);
    }

    @Override
    public Long queryUserIdByOrgId(Long orgId) {
        return this.baseMapper.selectUserIdByOrgId(orgId);
    }

    /**
     * 递归查询所有子节点
     * @param allList 菜单集合
     * @param parentId 父级id
     * @return 子菜单集合
     */
    private List<SysOrgEntity> getAllChildrenList(List<SysOrgEntity> allList, Long parentId) {
        List<SysOrgEntity> childrenList = new ArrayList<>();
        // 判空
        if (allList == null || allList.size() == 0) {
            return childrenList;
        }
        // 找出所有的下一级节点
        for (SysOrgEntity org : allList) {
            if (parentId.equals(org.getPid())) {
                childrenList.add(org);
            }
        }
        // 当前所有子级集合
        List<SysOrgEntity> allChildrenList = new ArrayList<>(childrenList);
        // 遍历下一级节点
        if (CollUtil.isNotEmpty(childrenList)) {
            for (SysOrgEntity org : childrenList) {
                // 递归
                List<SysOrgEntity> children = getAllChildrenList(allList, org.getId());
                if (CollUtil.isNotEmpty(children)) {
                    allChildrenList.addAll(children);
                }
            }
        }
        return allChildrenList;
    }

    /**
     * 组织保存校验
     * @param entity 组织对象
     */
    private void orgSaveValidate(SysOrgEntity entity) {
        // 判断组织类型是否正确
        if (entity.getPid() == null || entity.getPid().equals(0L)) {
            return;
        }
        Integer currOrgType = entity.getOrgType();
        SysOrgEntity parent = this.getById(entity.getPid());
        Integer parentOrgType = parent.getOrgType();
        if (currOrgType < parentOrgType) {
            throw new RRException("组织类型级别不能高于父级");
        }

        // 判断组织编码是否重复
        List<SysOrgEntity> orgs = this.list(new QueryWrapper<SysOrgEntity>().lambda()
                .eq(SysOrgEntity::getOrgCode, entity.getOrgCode())
                .ne(entity.getId() != null, SysOrgEntity::getId, entity.getId()));
        if (CollectionUtil.isNotEmpty(orgs)) {
            throw new RRException("组织编码已存在");
        }
    }
}
